#include<iostream>
using namespace std;
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<string>
#include<string.h>
#include<stdio.h>
#include<cstdio>
#include<cstdlib>
const int basesize=1024;

const int garvnum=64;
const int envnum=64;
//全局命令
char* gargv[garvnum];
int gargc=0;

//全局的当前shell工作路径 
char pwd[basesize];
char pwdenv[basesize];

//全局变量表
char* env[envnum];




string GetUserName()
{
   string name=getenv("USER");
   return name.empty()?"NoUser":name;
}
string GetHostName()
{
   string hostname=getenv("HOSTNAME");
   return hostname.empty()?"NoHost":hostname;
}

string GetPWD()
{
   // string pwd=getenv("PWD");
   // return pwd.empty()?"NoPWD":pwd;
   //char pwd[basesize];
   if(nullptr==getcwd(pwd,sizeof(pwd)))
   {
      return "NOne";
   }
   snprintf(pwdenv,sizeof(pwd),"PWD=%s",pwd);
   putenv(pwdenv);
   return pwd;
}
void addenv(const char* str)
{
   int idex=0;
   while(env[idex])
   {
     idex++;
   }
   env[idex]=(char*)malloc(strlen(str)+1);
   strncpy(env[idex++],str,strlen(str)+1);
   env[idex]=nullptr;

   
}

string Commandline()
{
  //[gxy@iZ2ze2x8nrwwd0xw2vzsrhZ lesson20]
   char command_line[basesize];
   snprintf(command_line,basesize,"[%s@%s my  %s]$",GetUserName().c_str(), GetHostName().c_str(), GetPWD().c_str());
   return command_line;
}
void PrintCommand()
{
    printf("%s",Commandline().c_str());
    fflush(stdout);
}

bool GetCommandLine(char command_buffer[],int basesize)
{
   char* result=fgets(command_buffer, basesize,stdin);//stdin 标准输入
    if(!result)
    {
          return  false;
    }
    //末尾有个换行符 还要考虑这个命令是不是空指令 也就是只有换行符
    command_buffer[strlen(command_buffer)-1]=0;
    if(strlen(command_buffer)==0)
    {
      return false;
    }
    return true;

}
void  ParseCommandLine(char command_buffer[], int sz)
{
      (void)sz;
      memset(gargv,0,sizeof(gargv));
      gargc=0;
      const char* interval=" ";
      gargv[gargc++]=strtok(command_buffer,interval);//必须写第一个，因为第一次分析命令和之后分析命令 写的格式不一样

     // while((bool)(gargv[gargc++]=strtok(nullptr,interval)));//最后一个为空的时候也存进去 因为你也有空命令的时候，一起分析了
      while((bool)(gargv[gargc++] = strtok(nullptr, interval)));
      gargc--;

}
bool ExecuteCommand()
{
  //让子进程进行
   pid_t id=fork();
   if(id<0)
   {
     cout<<"执行失败"<<endl;
   }
   if(id==0)//子进程
   {
     execvp(gargv[0],gargv);
     exit(1);
   }
   int status=0;
   if(id>0)
   {
     pid_t rid=waitpid(id,&status,0);
     if(rid>0)//
     {
       return true;
     }
   
    
   }
   return false;

}
void debug()
{
 printf("%d\n",gargc);
 for(int i=0;gargv[i];i++)
 {
   printf("gargv[%d]=%s\n",i,gargv[i]);
 }
}
bool CheckBuildCommand()
{
   if(strcmp(gargv[0],"cd")==0)
   {
      if(gargc==2)
      {
        //cout<<"已经执行chdir"<<endl;
        chdir(gargv[1]);
        
      }
      return true;
   }
   else if(strcmp(gargv[0],"export")==0)
   {
      if(gargc==2)
      {
         addenv(gargv[1]);
      }
      return true;
   }
   else if(strcmp(gargv[0],"env")==0)
   {
       for(int i=0;env[i];i++)
       {
        printf("%s\n",env[i]);
       }
       return true;
   }
   return false;
}
void InitEnv()
{
  extern char** environ;
   int index=0;
   while(environ[index])
   {
      env[index]=(char*)malloc(strlen(environ[index])+1);
      strncpy(env[index],environ[index],strlen(environ[index])+1);
      index++;
   }
   env[index]=nullptr;

}
int main()
{
  InitEnv();
  char command_buffer[basesize];
  while(true)
  {

    PrintCommand();//打印命令行
    
    if(!GetCommandLine(command_buffer,basesize) )   // 2. 获取用户命令
        {
            continue;
        }
      
     //"ls -a -b -c -d"->"ls" "-a" "-b" "-c" "-d"
        ParseCommandLine(command_buffer, strlen(command_buffer)); // 3. 分析命令
       // debug();
        if(CheckBuildCommand())
         { 
           //cout<<"进来了"<<endl;
           continue;
         }
         ExecuteCommand();   // 4. 执行命令
  }
}
